﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
using System.Linq;
using System.Text;
using ComHlp.Classes;
using ComHlp.Classes.Net;
using ComHlp.ContentClasses;
using ComHlp.ContentClasses.Connections;
using ComHlp.ContentClasses.FormDef;
using ComHlp.ContentClasses.VirtualControls;
using ComHlp.enums;
using ComHlp.enums.Fields;
using ComHlp.Exceptions;
using System.Data;
namespace ConsoleClient
{
    public class ITXCLIENT
    {
        ClientConnection connection;
        /*
        ClientConnection connection = new ClientConnection
        {
            Codepage = ItxCodepage.Cp850,
            ServerHostname = "srv2k8-main",
            ServerService = 4714
        };*/
        /// <summary>
        /// "220.180.51.106",
        /// </summary>
        public string Server
        {
            get;
            set;
        }
        public string Command = "";
        public string Trans = "";
        public string DataMap = "";
        /// <summary>
        /// 25002
        /// </summary>
        public int Port
        {
            get;
            set;
        }
        public int Connect()
        {
            connection = new ClientConnection
            {
                Codepage = ItxCodepage.Cp850,
                ServerHostname = Server,
                ServerService = Port
            };
            // init communication and connect 
            _itxCom = new ItxCom(connection, true, 333, "601c", 30, false, false);

            try
            {
                // get screen 'content'
                currentMessage = _itxCom.ConnectToServer();
                // get map layout
                currentMapData = _itxCom.RequestMapData(currentMessage.Response);
            }
            catch (CommunicationException exc)
            {
                Console.WriteLine($"Problem: {exc.Message}");
                _itxCom.DisconnectFromServer();
                return -1;
            }
            // write status
            Console.WriteLine($"Status: {currentMapData.BsMap.Status.StatusMessage}");
            //
            // now - let us search for the fields BENID, PASSW and client (DM05 for field names)
            FindFieldAndInsertValue(currentMapData.FormDefMap, "BENID", "INTEXE");
            FindFieldAndInsertValue(currentMapData.FormDefMap, "PASSW", "intex95");
            FindFieldAndInsertValue(currentMapData.FormDefMap, "MANDANT", "00");
            return 0;
        }
        ItxServerMessage currentMessage;
        MapParsingResult currentMapData;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="Transation"=HR20></param>
        /// <param name="cmd"=I></param>
        /// <returns></returns>
        public DataSet Commnicate(string Transation, string cmd)
        {
            DataSet SResult =null;
            // directly go to hr20
            FindFieldAndInsertValue(currentMapData.FormDefMap, "FCSONDER", Transation);//only named on GM01 FCSONDER
            // build string for sending to the server
            string responseString = BuildResponseString(currentMapData.CurrentBs, currentMapData.FormDefMap);

            // auth!
            if (!PerformServerRequest(ref currentMessage, ref currentMapData, responseString))
                return SResult;
            Console.WriteLine($"Status: {currentMapData.BsMap.Status.StatusMessage}");


            // enter I into modify/vkz field for hr20
            FindFieldAndInsertValue(currentMapData.FormDefMap, "VKZ", cmd);
            responseString = BuildResponseString(currentMapData.CurrentBs, currentMapData.FormDefMap);
            if (!PerformServerRequest(ref currentMessage, ref currentMapData, responseString))
                return SResult;
            SResult = Convert2DataSet(responseString);
            return SResult;
        }
        public DataSet Convert2DataSet(string responseString)
        {
            DataSet SResult = new DataSet();
            /*
            Console.WriteLine($"Lastname: {currentMapData.FormDefMap.Fields.FirstOrDefault(x => x.FormDefName == "NNAME")?.BsContent}");
            Console.WriteLine($"Firstname: {currentMapData.FormDefMap.Fields.FirstOrDefault(x => x.FormDefName == "VNAME")?.BsContent}");*/
            Console.WriteLine($"Status: {currentMapData.BsMap.Status.StatusMessage}");
            DataTable tb = new DataTable();
            tb.Columns.Add("STATUSITX");
            tb.Columns.Add("MAPDEF");
            tb.Columns.Add("MAPVAR");
            tb.Columns.Add("MAPCONTENT");
            foreach (ItxField fld in currentMapData.FormDefMap.Fields)
            {
                if (tb.Columns.Contains(fld.FormDefName)) continue;
                tb.Columns.Add(fld.FormDefName); 
                 
            }
            try
            {
                DataRow dwData = tb.Rows.Add();
                dwData["STATUSITX"] = currentMapData.BsMap.Status.StatusMessage;
                dwData["MAPDEF"] = "";
                dwData["MAPVAR"] = "";
                dwData["MAPCONTENT"] = "";
                string MAPDEF = "";
                string MAPVAR = "";
                string MAPCONTENT = "";
                foreach (ItxField fld in currentMapData.FormDefMap.Fields)
                {
                    MAPDEF += fld.FormDefName;
                    MAPVAR += ":"+fld.FormDefName+":";
                    MAPCONTENT += fld.BsContent;
                    dwData[fld.FormDefName] = fld.BsContent;
                }
                dwData["MAPDEF"] = MAPDEF;
                dwData["MAPVAR"] = MAPVAR;
                dwData["MAPCONTENT"] = MAPCONTENT;
                SResult.Tables.Add(tb);
            }
            catch(Exception ex)
            {
              
            }
          
            /*
            for (int i = 0; i < 10; i++)
            {
                // pagedown
                FindFieldAndInsertValue(currentMapData.FormDefMap, "FC", "F8");
                responseString = BuildResponseString(currentMapData.CurrentBs, currentMapData.FormDefMap);
                if (!PerformServerRequest(ref currentMessage, ref currentMapData, responseString))
                    return SResult;

                Console.WriteLine($"Lastname: {currentMapData.FormDefMap.Fields.FirstOrDefault(x => x.FormDefName == "NNAME")?.BsContent}");
                Console.WriteLine($"Firstname: {currentMapData.FormDefMap.Fields.FirstOrDefault(x => x.FormDefName == "VNAME")?.BsContent}");
                Console.WriteLine($"Status: {currentMapData.BsMap.Status.StatusMessage}");
            } 
            Console.WriteLine("Press any key to continue...");
            Console.Read();*/
            return SResult;
        }
        public ITXCLIENT()
        {
             
        }
        ~ITXCLIENT()
        {
            if (_itxCom == null) return;
            _itxCom.DisconnectFromServer();
        }
        public ITXCLIENT(string _Server,int _port)
        {
            Server = _Server;
            Port = _port;
            Connect();
        }
        private static ItxCom _itxCom;
        private static bool PerformServerRequest(ref ItxServerMessage currentMessage, ref MapParsingResult currentMapData, string responseString)
        {
            try
            {
                // send to server
                currentMessage = _itxCom.SendRequestToServer(ItxServerMessageType.ScreenContent, responseString);
                // get new mapdata?
                currentMapData = _itxCom.RequestMapData(currentMessage.Response);
                return true;
            }
            catch (CommunicationException exc)
            {
                Console.WriteLine($"Problem: {exc.Message}");
                _itxCom.DisconnectFromServer();
                return false;
            }
        }

        static bool FindFieldAndInsertValue(FormDefMap formDefMap, string fieldName, string content)
        {
            var benIdField = formDefMap.Fields.FirstOrDefault(x => x.FormDefName == fieldName);
            if (benIdField == null)
            {
                Console.WriteLine($"Unable to find field {fieldName}");
                return false;
            }
            benIdField.BsContent = content;
            return true;
        }

        private static string BuildResponseString(string currentBs, FormDefMap formDefMap)
        {
            BsResponseHelper bsResponseHelper = new BsResponseHelper();

            // fill initial string
            StringBuilder sbResponse = new StringBuilder();
            sbResponse.Append(currentBs);
            // set dummy mousex/mousey (else monp3u will crash hrhrhr)
            sbResponse.Replace(' ', '0', 426, 8);
            // calculate length from formdef header (where to start field content replace)
            int length = 438 + 10 * formDefMap.Header.MapFieldCount;

            // add field content
            foreach (ItxField itxField in formDefMap.Fields)
            {
                // first check special fields
                switch (itxField.FormDefName)
                {
                    case ItxControlConstants.FormDefFcSonderName:
                    case ItxControlConstants.FormDefFcName:
                        length = bsResponseHelper.InsertValueIntoBsResponse(sbResponse, itxField.BsContent, length, itxField.Length);
                        continue;
                    case ItxControlConstants.FormDefFunctionName:
                        length = bsResponseHelper.InsertValueIntoBsResponse(sbResponse, itxField.BsContent, length, itxField.Length);
                        continue;
                    default:
                        // don't touch content of this special fields (FC/FKT are also inside this group)
                        if (itxField.MapFieldType == ItxProtocolFieldType.DataAreaSpecialMonitor)
                        {
                            length = length + itxField.Length;
                            continue;
                        }
                        break;
                }

                // now buttons
                switch (itxField.FieldType)
                {
                    // not handled
                    case ItxFieldType.Button:
                        {
                            length = bsResponseHelper.InsertValueIntoBsResponse(sbResponse, "", length, itxField.Length);
                            continue;
                        }
                    // not handled
                    case ItxFieldType.ListViewAddition:
                        {
                            length = bsResponseHelper.InsertValueIntoBsResponse(sbResponse, "", length, itxField.Length);
                            continue;
                        }
                    // not handled
                    case ItxFieldType.ListViewVm:
                        {
                            length = bsResponseHelper.InsertValueIntoBsResponse(sbResponse, "", length, itxField.Length);
                            continue;
                        }
                    // not handled
                    case ItxFieldType.ListViewVm2:
                        {
                            length = bsResponseHelper.InsertValueIntoBsResponse(sbResponse, "", length, itxField.Length);
                            continue;
                        }
                }

                // normal operations (build response)
                string input;
                switch (itxField.Attrib3Casing)
                {
                    case ItxCharacterCasing.Upper:
                        input = itxField.BsContent.ToUpper();
                        break;
                    //case CharacterCasing.Normal:
                    default:
                        input = itxField.BsContent;
                        break;
                }
                length = bsResponseHelper.InsertValueIntoBsResponse(sbResponse, input, length, itxField.Length);
                // nothing found, replace with spaces
                //length = bsResponseHelper.InsertValueIntoBsResponse(sbResponse, "", length, itxField.Length);
            }
            sbResponse.Remove(length, sbResponse.Length - length);

            /* fill string with spaces
             *  < currentBs.Length due to the X we need to add at the end
            */
            for (int i = length; i < currentBs.Length - 1; i++)
                sbResponse.Append(' ');
            sbResponse.Append('X');
            return sbResponse.ToString();
        }
    }
}
